<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>系统总体架构图 - 基于LLM的城市规划GIS系统</title>
    <style>
        :root {
            --bg-color: #121212;
            --text-color: #e0e0e0;
            --primary-color: #00c3ff;
            --secondary-color: #7b2ff7;
            --accent-color: #00ff8f;
            --dark-panel: #232323;
            --panel-border: #3a3a3a;
            --glow-blue: 0 0 15px rgba(0, 195, 255, 0.7);
            --glow-purple: 0 0 15px rgba(123, 47, 247, 0.7);
            --glow-green: 0 0 15px rgba(0, 255, 143, 0.7);
        }

        body {
            background-color: var(--bg-color);
            color: var(--text-color);
            font-family: 'Arial', sans-serif;
            margin: 0;
            padding: 0;
            line-height: 1.6;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }

        header {
            text-align: center;
            margin-bottom: 40px;
            padding: 25px;
            background-color: var(--dark-panel);
            border-radius: 8px;
            border: 1px solid var(--panel-border);
            box-shadow: 0 0 20px rgba(0, 195, 255, 0.3);
        }

        h1 {
            color: var(--primary-color);
            margin: 0;
            font-size: 2.5em;
            text-shadow: var(--glow-blue);
        }

        .subtitle {
            color: var(--accent-color);
            font-size: 1.2em;
            margin-top: 10px;
        }

        .architecture-container {
            position: relative;
            width: 100%;
            height: 750px;
            background-color: var(--dark-panel);
            border-radius: 8px;
            border: 1px solid var(--panel-border);
            overflow: hidden;
        }

        /* 添加分层标签 */
        .layer-label {
            position: absolute;
            font-size: 1.3em;
            font-weight: bold;
            color: var(--text-color);
            text-align: center;
            width: 200px;
            padding: 5px 10px;
            border-radius: 5px;
            background-color: rgba(35, 35, 35, 0.8);
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
        }

        .frontend-label {
            top: 10px;
            left: 450px;
            color: var(--primary-color);
        }

        .backend-label {
            top: 310px;
            left: 150px;
            color: var(--secondary-color);
        }

        .external-label {
            top: 310px;
            left: 750px;
            color: var(--accent-color);
        }

        .component {
            position: absolute;
            background-color: rgba(35, 35, 35, 0.9);
            border: 2px solid;
            border-radius: 10px;
            padding: 15px;
            text-align: center;
            transition: all 0.3s ease;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
            z-index: 10;
        }

        .component:hover {
            transform: translateY(-5px) scale(1.03);
            box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
            z-index: 20;
        }

        /* 添加组件连接点样式 */
        .component::before {
            content: '';
            position: absolute;
            width: 12px;
            height: 12px;
            background-color: inherit;
            border-radius: 50%;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 5;
            box-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .component:hover::before {
            opacity: 1;
        }

        .component h3 {
            margin-top: 0;
            font-size: 1.2em;
        }

        .component-content {
            font-size: 0.9em;
            text-align: left;
        }

        .frontend {
            border-color: var(--primary-color);
            box-shadow: var(--glow-blue);
        }

        .backend {
            border-color: var(--secondary-color);
            box-shadow: var(--glow-purple);
        }

        .external {
            border-color: var(--accent-color);
            box-shadow: var(--glow-green);
        }

        .connection {
            position: absolute;
            transform-origin: 0 0;
            z-index: 1;
            height: 4px !important;
            border-radius: 4px;
            transition: all 0.3s ease;
            opacity: 0.7;
        }

        .connection-label {
            position: absolute;
            background-color: rgba(35, 35, 35, 0.9);
            padding: 6px 12px;
            border-radius: 6px;
            font-size: 0.9em;
            font-weight: bold;
            white-space: nowrap;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
            border: 1px solid rgba(255, 255, 255, 0.2);
            z-index: 10;
            transition: all 0.3s ease;
        }

        .connection-frontend {
            background-color: var(--primary-color);
            box-shadow: 0 0 15px var(--primary-color);
        }

        .connection-backend {
            background-color: var(--secondary-color);
            box-shadow: 0 0 15px var(--secondary-color);
        }

        .connection-external {
            background-color: var(--accent-color);
            box-shadow: 0 0 15px var(--accent-color);
        }

        /* 高亮连接线效果 */
        .connection.highlight {
            height: 8px !important;
            opacity: 1;
            z-index: 5;
        }

        .connection-label.highlight {
            transform: scale(1.15);
            z-index: 15;
            box-shadow: 0 0 20px rgba(255, 255, 255, 0.8);
            font-weight: bold;
        }

        .connection-arrow {
            position: absolute;
            width: 0;
            height: 0;
            border-style: solid;
            transform-origin: 0 0;
            z-index: 5;
        }

        .legend {
            display: flex;
            justify-content: center;
            margin-top: 30px;
            gap: 20px;
        }

        .legend.connection-legend {
            margin-top: 10px;
        }

        .legend-item {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .legend-color {
            width: 20px;
            height: 20px;
            border-radius: 4px;
        }

        .frontend-color {
            background-color: var(--primary-color);
            box-shadow: var(--glow-blue);
        }

        .backend-color {
            background-color: var(--secondary-color);
            box-shadow: var(--glow-purple);
        }

        .external-color {
            background-color: var(--accent-color);
            box-shadow: var(--glow-green);
        }

        .connection-frontend-color {
            background-color: var(--primary-color);
            box-shadow: var(--glow-blue);
        }

        .connection-backend-color {
            background-color: var(--secondary-color);
            box-shadow: var(--glow-purple);
        }

        .connection-external-color {
            background-color: var(--accent-color);
            box-shadow: var(--glow-green);
        }

        footer {
            text-align: center;
            margin-top: 40px;
            font-size: 0.9em;
            color: #888;
        }

        @keyframes pulse {
            0% {
                opacity: 0.6;
                box-shadow: 0 0 5px var(--primary-color);
            }
            50% {
                opacity: 1;
                box-shadow: 0 0 15px var(--primary-color);
            }
            100% {
                opacity: 0.6;
                box-shadow: 0 0 5px var(--primary-color);
            }
        }

        .connection-frontend {
            animation: pulse-blue 2s infinite;
        }

        .connection-backend {
            animation: pulse-purple 2s infinite;
        }

        .connection-external {
            animation: pulse-green 2s infinite;
        }

        @keyframes pulse-blue {
            0% {
                opacity: 0.6;
                box-shadow: 0 0 5px var(--primary-color);
            }
            50% {
                opacity: 1;
                box-shadow: 0 0 15px var(--primary-color);
            }
            100% {
                opacity: 0.6;
                box-shadow: 0 0 5px var(--primary-color);
            }
        }

        @keyframes pulse-purple {
            0% {
                opacity: 0.6;
                box-shadow: 0 0 5px var(--secondary-color);
            }
            50% {
                opacity: 1;
                box-shadow: 0 0 15px var(--secondary-color);
            }
            100% {
                opacity: 0.6;
                box-shadow: 0 0 5px var(--secondary-color);
            }
        }

        @keyframes pulse-green {
            0% {
                opacity: 0.6;
                box-shadow: 0 0 5px var(--accent-color);
            }
            50% {
                opacity: 1;
                box-shadow: 0 0 15px var(--accent-color);
            }
            100% {
                opacity: 0.6;
                box-shadow: 0 0 5px var(--accent-color);
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>基于LLM的城市规划GIS系统架构图</h1>
            <div class="subtitle">大型语言模型与地理信息系统的人机交互</div>
        </header>

        <div class="architecture-container" id="architecture">
            <!-- 分层标签 -->
            <div class="layer-label frontend-label">前端层</div>
            <div class="layer-label backend-label">后端层</div>
            <div class="layer-label external-label">外部服务层</div>
            <!-- 组件和连接将通过JavaScript动态生成 -->
        </div>

        <div class="legend">
            <div class="legend-item">
                <div class="legend-color frontend-color"></div>
                <span>前端组件</span>
            </div>
            <div class="legend-item">
                <div class="legend-color backend-color"></div>
                <span>后端组件</span>
            </div>
            <div class="legend-item">
                <div class="legend-color external-color"></div>
                <span>外部服务</span>
            </div>
        </div>

        <div class="legend connection-legend">
            <div class="legend-item">
                <div class="legend-color connection-frontend-color"></div>
                <span>前端内部通信</span>
            </div>
            <div class="legend-item">
                <div class="legend-color connection-backend-color"></div>
                <span>后端内部通信</span>
            </div>
            <div class="legend-item">
                <div class="legend-color connection-external-color"></div>
                <span>外部服务通信</span>
            </div>
        </div>

        <footer>
            © 2024 基于LLM的城市规划GIS系统 | 科技感城市AI设计风格
        </footer>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const architecture = document.getElementById('architecture');

            // 定义组件
            const components = [
                // 前端组件 - 上方
                {
                    id: 'vue-app',
                    name: 'Vue 应用',
                    content: 'Vue 3 + TypeScript<br>Element Plus UI<br>Pinia 状态管理',
                    x: 120, y: 50, width: 200, height: 100,
                    type: 'frontend'
                },
                {
                    id: 'map-module',
                    name: '地图操作模块',
                    content: 'ArcGIS API<br>地图要素管理<br>空间分析功能',
                    x: 450, y: 50, width: 200, height: 100,
                    type: 'frontend'
                },
                {
                    id: 'ai-module',
                    name: 'AI指令处理模块',
                    content: 'TypeChat<br>指令解析<br>指令执行管理',
                    x: 780, y: 50, width: 200, height: 100,
                    type: 'frontend'
                },
                {
                    id: 'state-management',
                    name: '状态管理',
                    content: 'Pinia Store<br>指令队列<br>执行结果存储',
                    x: 450, y: 200, width: 200, height: 100,
                    type: 'frontend'
                },

                // 后端组件 - 左下方
                {
                    id: 'aspnet-api',
                    name: 'ASP.NET Core API',
                    content: 'RESTful API<br>JWT认证<br>控制器',
                    x: 150, y: 350, width: 200, height: 100,
                    type: 'backend'
                },
                {
                    id: 'data-operations',
                    name: '数据操作层',
                    content: 'Entity Framework Core<br>数据访问<br>业务逻辑',
                    x: 150, y: 480, width: 200, height: 100,
                    type: 'backend'
                },
                {
                    id: 'sql-database',
                    name: 'SQL Server 数据库',
                    content: 'ASP.NET Identity<br>用户管理<br>系统配置',
                    x: 150, y: 610, width: 200, height: 100,
                    type: 'backend'
                },

                // 外部服务 - 右下方
                {
                    id: 'arcgis-online',
                    name: 'ArcGIS Online',
                    content: 'FeatureLayer<br>空间数据存储<br>地理处理服务',
                    x: 750, y: 350, width: 200, height: 100,
                    type: 'external'
                },
                {
                    id: 'llm-service',
                    name: 'LLM服务',
                    content: 'DeepSeek AI<br>自然语言处理<br>指令生成',
                    x: 750, y: 480, width: 200, height: 100,
                    type: 'external'
                },
                {
                    id: 'gaode-api',
                    name: '高德地图API',
                    content: 'POI搜索<br>地理编码<br>路径规划',
                    x: 750, y: 610, width: 200, height: 100,
                    type: 'external'
                }
            ];

            // 定义连接
            const connections = [
                { from: 'vue-app', to: 'map-module', label: '调用', type: 'frontend' },
                { from: 'map-module', to: 'ai-module', label: '调用', type: 'frontend' },
                { from: 'vue-app', to: 'state-management', label: '状态更新', type: 'frontend' },
                { from: 'map-module', to: 'state-management', label: '状态更新', type: 'frontend' },
                { from: 'ai-module', to: 'state-management', label: '状态更新', type: 'frontend' },
                { from: 'vue-app', to: 'aspnet-api', label: 'HTTP请求', type: 'backend' },
                { from: 'aspnet-api', to: 'data-operations', label: '调用', type: 'backend' },
                { from: 'data-operations', to: 'sql-database', label: 'CRUD操作', type: 'backend' },
                { from: 'state-management', to: 'arcgis-online', label: 'REST API', type: 'external' },
                { from: 'state-management', to: 'llm-service', label: 'API调用', type: 'external' },
                { from: 'state-management', to: 'gaode-api', label: 'API调用', type: 'external' }
            ];

            // 创建组件
            components.forEach(comp => {
                const element = document.createElement('div');
                element.id = comp.id;
                element.className = `component ${comp.type}`;
                element.style.left = `${comp.x}px`;
                element.style.top = `${comp.y}px`;
                element.style.width = `${comp.width}px`;
                element.style.height = `${comp.height}px`;
                element.dataset.id = comp.id;

                element.innerHTML = `
                    <h3>${comp.name}</h3>
                    <div class="component-content">${comp.content}</div>
                `;

                // 添加鼠标悬停事件
                element.addEventListener('mouseenter', function() {
                    highlightConnections(comp.id);
                });

                element.addEventListener('mouseleave', function() {
                    resetConnections();
                });

                architecture.appendChild(element);
            });

            // 创建连接
            connections.forEach(conn => {
                setTimeout(() => {
                    drawConnection(conn.from, conn.to, conn.label, conn.type);
                }, 100); // 延迟一点以确保组件已渲染
            });

            // 高亮显示与指定组件相关的所有连接
            function highlightConnections(componentId) {
                // 高亮组件
                const component = document.getElementById(componentId);
                component.style.transform = 'scale(1.05)';
                component.style.zIndex = '20';

                // 查找与该组件相关的所有连接
                connections.forEach((conn, index) => {
                    if (conn.from === componentId || conn.to === componentId) {
                        // 高亮连接线
                        const connectionElements = document.querySelectorAll(`.connection[data-from="${conn.from}"][data-to="${conn.to}"]`);
                        const labelElements = document.querySelectorAll(`.connection-label[data-from="${conn.from}"][data-to="${conn.to}"]`);
                        const arrowElements = document.querySelectorAll(`.connection-arrow[data-from="${conn.from}"][data-to="${conn.to}"]`);

                        connectionElements.forEach(el => el.classList.add('highlight'));
                        labelElements.forEach(el => el.classList.add('highlight'));
                        arrowElements.forEach(el => el.classList.add('highlight'));

                        // 高亮相关组件
                        const relatedComponentId = conn.from === componentId ? conn.to : conn.from;
                        const relatedComponent = document.getElementById(relatedComponentId);
                        if (relatedComponent) {
                            relatedComponent.style.transform = 'scale(1.03)';
                            relatedComponent.style.zIndex = '15';
                        }
                    }
                });
            }

            // 重置所有连接的高亮状态
            function resetConnections() {
                // 重置组件
                document.querySelectorAll('.component').forEach(comp => {
                    comp.style.transform = '';
                    comp.style.zIndex = '';
                });

                // 重置连接线
                document.querySelectorAll('.connection, .connection-label, .connection-arrow').forEach(el => {
                    el.classList.remove('highlight');
                });
            }

            // 绘制连接线
            function drawConnection(fromId, toId, label, type) {
                const fromElement = document.getElementById(fromId);
                const toElement = document.getElementById(toId);

                if (!fromElement || !toElement) return;

                const fromRect = fromElement.getBoundingClientRect();
                const toRect = toElement.getBoundingClientRect();
                const archRect = architecture.getBoundingClientRect();

                // 计算相对于架构容器的位置
                const fromX = fromRect.left + fromRect.width/2 - archRect.left;
                const fromY = fromRect.top + fromRect.height/2 - archRect.top;
                const toX = toRect.left + toRect.width/2 - archRect.left;
                const toY = toRect.top + toRect.height/2 - archRect.top;

                // 计算连接线长度和角度
                const length = Math.sqrt(Math.pow(toX - fromX, 2) + Math.pow(toY - fromY, 2));
                const angle = Math.atan2(toY - fromY, toX - fromX) * 180 / Math.PI;

                // 创建连接线
                const connection = document.createElement('div');
                connection.className = `connection connection-${type}`;
                connection.style.width = `${length - 15}px`; // 减少一点长度，为箭头留空间
                connection.style.left = `${fromX}px`;
                connection.style.top = `${fromY}px`;
                connection.style.transform = `rotate(${angle}deg)`;

                // 添加数据属性，用于高亮显示
                connection.dataset.from = fromId;
                connection.dataset.to = toId;
                connection.dataset.type = type;

                // 创建箭头
                const arrowSize = 12; // 增大箭头尺寸
                const arrow = document.createElement('div');
                arrow.className = `connection-arrow connection-${type}`;

                // 设置箭头样式
                arrow.style.borderWidth = `${arrowSize}px 0 ${arrowSize}px ${arrowSize * 1.5}px`;
                arrow.style.borderColor = `transparent transparent transparent var(--${type === 'frontend' ? 'primary' : type === 'backend' ? 'secondary' : 'accent'}-color)`;

                // 添加数据属性，用于高亮显示
                arrow.dataset.from = fromId;
                arrow.dataset.to = toId;
                arrow.dataset.type = type;

                // 计算箭头位置
                const arrowX = fromX + Math.cos(angle * Math.PI / 180) * (length - 15);
                const arrowY = fromY + Math.sin(angle * Math.PI / 180) * (length - 15);

                arrow.style.left = `${arrowX}px`;
                arrow.style.top = `${arrowY}px`;
                arrow.style.transform = `rotate(${angle}deg)`;

                // 创建标签
                const labelElement = document.createElement('div');
                labelElement.className = 'connection-label';
                labelElement.textContent = label;

                // 添加数据属性，用于高亮显示
                labelElement.dataset.from = fromId;
                labelElement.dataset.to = toId;
                labelElement.dataset.type = type;

                // 计算标签位置
                const labelX = fromX + (toX - fromX) / 2;
                const labelY = fromY + (toY - fromY) / 2;

                labelElement.style.left = `${labelX - 30}px`;
                labelElement.style.top = `${labelY - 15}px`;

                // 添加到DOM
                architecture.appendChild(connection);
                architecture.appendChild(arrow);
                architecture.appendChild(labelElement);

                // 添加点击事件，点击连接线时高亮显示相关组件
                [connection, arrow, labelElement].forEach(el => {
                    el.addEventListener('mouseenter', function() {
                        // 高亮连接线
                        connection.classList.add('highlight');
                        arrow.classList.add('highlight');
                        labelElement.classList.add('highlight');

                        // 高亮相关组件
                        const fromComponent = document.getElementById(fromId);
                        const toComponent = document.getElementById(toId);

                        if (fromComponent) {
                            fromComponent.style.transform = 'scale(1.05)';
                            fromComponent.style.zIndex = '20';
                        }

                        if (toComponent) {
                            toComponent.style.transform = 'scale(1.05)';
                            toComponent.style.zIndex = '20';
                        }
                    });

                    el.addEventListener('mouseleave', function() {
                        // 重置高亮状态
                        resetConnections();
                    });
                });
            }
        });
    </script>
</body>
</html>
